import { ICommand } from "./command/ICommand";

export class RenderCommandSystem {
    /**
     * 组装的渲染命令列表
     */
    cmdList: { [cmdIndex: number]: ICommand } = {};
    /**
     * 与渲染命令列表配合的参数列表
     */
    paramList: {
        [cmdIndex: number]: {
            executionLevel: ExecutionLevel,
            [otherCmdConfigKey: string]: any
        }
    } = {};
    /**
     * 当前正在执行的渲染命令序号
     */
    cmdIndex = 0;
    /**
     * 渲染命令列表长度
     */
    cmdListLength = 0;
    /**
     * 控制添加参数
     */
    cmdIsOpen = false;
    /**
     * 有未执行完的渲染列表
     * 控制是否执行
     */
    cmdListActive = false;
    /**
     * 一帧的毫秒时间预算
     *
     * 渲染命令 模型渲染命令使用了
     */
    frameBudget = 32;
    /**
     * true:命令列表可以继续执行
     * false:因超时等命令列表被中断
     */
    continueExecution = true;
    // /**
    //  * 本列表共使用了几个tick
    //  */
    // tickCount = 0;


    setFrame(msPerFrameBudget: number) {
        this.frameBudget = msPerFrameBudget;
    }
    beginCommandSet() {
        this.cmdIndex = 0;
        this.cmdListLength = 0;
        // this.tickCount = 0;
        this.cmdListActive = true;
        this.paramList = {};
        this.cmdList = {};
    }
    addCMD(cmd: ICommand, executionLevel: ExecutionLevel = ExecutionLevel.normal): number {
        if (!cmd) {
            return this.cmdListLength;
        }
        if (this.cmdIsOpen) {
            this.cmdListLength++;
        }
        this.cmdIsOpen = true;
        this.cmdList[this.cmdListLength] = cmd;

        this.addParam("executionLevel", executionLevel);
        return this.cmdListLength;
    }
    /**
     * 添加当前的渲染命令参数
     *
     * 注意这里使用的是this.cmdListLength，因为此值还未更新，正好是最新的命令序号
     * @param key
     * @param val
     */
    addParam(key: string, val: any) {
        if (this.cmdIsOpen) {
            if (!this.paramList[this.cmdListLength]) {
                this.paramList[this.cmdListLength] = {} as any;
            }
            this.paramList[this.cmdListLength][key] = val;
        }
    }
    endCommandSet() {
        if (this.cmdIsOpen) {
            this.cmdIsOpen = false;
            this.cmdListLength++;
        }
    }
    getParam(key: string) {
        return this.paramList[this.cmdIndex][key];
    }
    executeCommandList() {
        if (this.cmdListActive) {
            // this.frameRemaining = this.frameBudget;
            /**
             * 时间够，继续做
             */
            this.continueExecution = true;
            /**
             * 从哪里开始执行 == 上次结束的位置+1
             */
            let restartIdx = 0;
            // const afterCmdList: { [cmdListNumber: number]: ICommand } = {};
            // let afterCmdIndex = 0;
            // let afterCmdLength = 0;

            /**
             * 正儿八经命令列表
             * 无论如何全部过一遍，因为可能后面有高等级的指令
             * 每个元素根据等级不同作不同处理
             * 时间不够后，不执行普通指令，但是高级指令也要执行
             */
            while (this.cmdIndex < this.cmdListLength) {
                // // 优先命令
                // if (this.paramList[this.cmdIndex].executionLevel == ExecutionLevel.alwaysDo) {
                //     this.cmdList[this.cmdIndex].execute();
                //     this.cmdIndex++;
                //     continue;
                // }
                // // 帧后执行的命令
                // if (this.paramList[this.cmdIndex].executionLevel == ExecutionLevel.doAfter) {
                //     afterCmdList[afterCmdLength++] = this.cmdList[this.cmdIndex];
                //     this.cmdIndex++;
                //     continue;
                // }
                // 正常渲染指令
                if (this.continueExecution && !this.paramList[this.cmdIndex].executionLevel || this.paramList[this.cmdIndex].executionLevel == ExecutionLevel.normal) {
                    const notEnoughTime = this.cmdList[this.cmdIndex].execute();
                    if (notEnoughTime) {
                        restartIdx = this.cmdIndex; // 这个指令没执行完，重新执行。更细致的现场保护由指令内部完成
                        this.continueExecution = false;
                    }
                    this.cmdIndex++;
                }
            }
            // /**
            //  * 临时构建的帧后指令
            //  */
            // while (afterCmdIndex < afterCmdLength) {
            //     afterCmdList[afterCmdIndex++].execute();
            // }
            // console.log("使用的帧数 ", this.tickCount, " 顺利执行=", this.continueExecution);
            // 时间充裕，全部执行完了
            if (this.continueExecution) {
                this.cmdListActive = false;
            }// 中断，保存现场
            else {
                this.cmdIndex = restartIdx;
            }
            // this.tickCount++;
            // console.log(this.tickCount);
            return;
        } else {
            return;
        }


    }

}
enum ExecutionLevel {
    normal = 0,
    doAfter = 1,
    alwaysDo = 2,
}